package com.ailot.cloud.gateway.init;

import com.ailot.cloud.base.common.constants.CommonConstant;
import com.ailot.cloud.gateway.entity.GatewayRouteList;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.annotation.Configuration;
import org.yaml.snakeyaml.Yaml;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * 初始化路由网关
 */
@Slf4j
@Configuration
@AllArgsConstructor
public class DynamicRouteInit {
    private RouteDefinitionWriter routeDefinitionWriter;
    private NacosConfigProperties nacosConfigProperties;

    @PostConstruct
    public void initRoute() {
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, nacosConfigProperties.getServerAddr());
            properties.put(PropertyKeyConst.USERNAME, nacosConfigProperties.getUsername());
            properties.put(PropertyKeyConst.PASSWORD, nacosConfigProperties.getPassword());
            ConfigService configService = NacosFactory.createConfigService(properties);
            String content = configService.getConfig(CommonConstant.CONFIG_DATA_ID, CommonConstant.CONFIG_GROUP, CommonConstant.CONFIG_TIMEOUT_MS);
            log.info("初始化路由网关开始");
            updateRoute(content);
            log.info("初始化路由网关完成");

            /**
             * 监听配置
             * 如果希望 Nacos 推送配置变更，可以使用 Nacos 动态监听配置接口来实现。
             */
            configService.addListener(CommonConstant.CONFIG_DATA_ID, CommonConstant.CONFIG_GROUP, new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    log.info("更新路由网关开始");
                    updateRoute(configInfo);
                    log.info("更新路由网关完成");
                }

                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
        } catch (NacosException e) {
            log.error("加载路由出错：{}", e.getErrMsg());
        }
    }

    public void updateRoute(String content) {
        Yaml yaml = new Yaml();
        GatewayRouteList gatewayRouteList = yaml.loadAs(content, GatewayRouteList.class);
        gatewayRouteList.getRoutes().forEach(route -> {
            log.info("加载路由：{},{}", route.getId(), route);
            routeDefinitionWriter.save(Mono.just(route)).subscribe();
        });
    }
}
